#ifndef LOG_ASYNCLOG_H
#define LOG_ASYNCLOG_H

#include "Logbuffer.h"
#include "thread/Latch.h"
#include "thread/Thread.h"

#include <condition_variable>
#include <memory>
#include <mutex>
#include <string>
#include <vector>

struct AsyncLogHelper;

class AsyncLog final {
public:
    using Buffer = Logbuffer<1 << (16 + 6)>; // 4M
    static constexpr std::size_t RESERVED_SIZE = 1 << 4;

    AsyncLog(
        std::size_t rollSize, std::string prefix, std::string suffix = ".log",
        bool rename = true);
    ~AsyncLog();

    const std::string &filename() const { return _filename; }

    void append(const char *buffer, std::size_t length);
    void start();
    void stop();

private:
    NONCOPYABLE(AsyncLog);

    void _append(AsyncLogHelper &helper);
    void _log_func();
    void _wait_for_append(AsyncLogHelper &helper);

    Thread _thread;
    Latch _latch;
    std::condition_variable _cv;
    std::mutex _mutex;
    const std::string _prefix;
    const std::string _suffix;
    std::string _filename;
    std::vector<std::unique_ptr<Buffer>> _buffers;
    std::unique_ptr<Buffer> _currentBuffer;
    std::unique_ptr<Buffer> _nextBuffer;
    const std::size_t _rollSize;
    std::atomic<bool> _running;
    const bool _rename;

};

#endif